﻿namespace YnabCsvConverter.Core 
{
   using System;
   using System.Globalization;
   using System.Text;
   using CsvHelper.Configuration;

   /// <summary>
   /// YnabRecord
   /// <example>
   /// Date,Payee,Category,Memo,Outflow,Inflow
   /// 07/25/10,Sample Payee,,Sample Memo for an outflow,100.00,
   /// 07/26/10,Sample Payee 2,,Sample memo for an inflow,,500.00
   ///
   /// INSTRUCTIONS: 1) Make your transactions look like the sample transactions above. (Those are just examples that you can delete) ,,,,,
   /// (Every field can be left blank except the date. Valid date formats:
   ///   DD/MM/YY
   ///   DD/MM/YYYY
   ///   DD/MM//YYYY
   ///   MM/DD/YY
   ///   MM/DD/YYYY
   ///   MM/DD//YYYY
   /// 2) (Don't forget to delete all of these instructions from the file before you try to import it).,,,,,
   /// 3) Save this file.,,,,,
   /// 4) Shut down the program you're using to edit this file.,,,,,
   /// 5) Import this file into YNAB 3.,,,,,
   /// </example>
   /// </summary>
   public class YnabRecord : IEquatable<YnabRecord>
   {
      /// <summary>
      /// Initializes a new instance of the <see cref="YnabRecord" /> class.
      /// </summary>
      public YnabRecord()
      {
         // This default data is used for creating the header line.
         Date = "Date";
         Payee = "Payee";
         Category = "Category";
         Memo = "Memo";
         Outflow = "Outflow";
         Inflow = "Inflow";
      }

      /// <summary>
      /// Gets or sets the date.
      /// </summary>
      /// <value>
      /// The date.
      /// </value>
      [CsvField(Index = 0)]
      public string Date { get; set; }

      /// <summary>
      /// Gets or sets the payee.
      /// </summary>
      /// <value>
      /// The payee.
      /// </value>
      [CsvField(Index = 1)]
      public string Payee { get; set; }

      /// <summary>
      /// Gets or sets the category.
      /// </summary>
      /// <value>
      /// The category.
      /// </value>
      [CsvField(Index = 2)]
      public string Category { get; set; }

      /// <summary>
      /// Gets or sets the memo.
      /// </summary>
      /// <value>
      /// The memo.
      /// </value>
      [CsvField(Index = 3)]
      public string Memo { get; set; }

      /// <summary>
      /// Gets or sets the outflow.
      /// </summary>
      /// <value>
      /// The outflow.
      /// </value>
      [CsvField(Index = 4)]
      public string Outflow { get; set; }

      /// <summary>
      /// Gets or sets the inflow.
      /// </summary>
      /// <value>
      /// The inflow.
      /// </value>
      [CsvField(Index = 5)]
      public string Inflow { get; set; }

      /// <summary>
      /// Sets the inflow outflow.
      /// </summary>
      /// <param name="amount">The amount.</param>
      public void SetInflowOutflow(decimal amount)
      {
         decimal amountAbs = Math.Abs(amount);

         if (amount < 0)
         {
            Inflow = string.Empty;
            Outflow = amountAbs.ToString(CultureInfo.InvariantCulture);
         }
         else
         {
            Inflow = amountAbs.ToString(CultureInfo.InvariantCulture);
            Outflow = string.Empty;
         }
      }

      /// <summary>
      /// Sets the inflow outflow.
      /// </summary>
      /// <param name="amount">The amount.</param>
      /// <param name="cultureInfo">The culture info.</param>
      public void SetInflowOutflow(string amount, CultureInfo cultureInfo)
      {
         decimal amountNum = decimal.Parse(amount, cultureInfo.NumberFormat);

         SetInflowOutflow(amountNum);
      }

      /// <summary>
      /// Sets the inflow outflow. (Uses invariant culture for parsing.)
      /// </summary>
      /// <param name="amount">The amount.</param>
      public void SetInflowOutflow(string amount)
      {
         decimal amountNum = decimal.Parse(amount, CultureInfo.InvariantCulture.NumberFormat);

         SetInflowOutflow(amountNum);
      }

      /// <summary>
      /// Sets the date.
      /// </summary>
      /// <param name="dateTime">The date time.</param>
      /// <param name="formatProvider">The format provider.</param>
      public void SetDate(string dateTime, IFormatProvider formatProvider)
      {
         Date = DateTime.Parse(dateTime, formatProvider).ToString("MM\\/dd\\/yyyy");     
      }

      /// <summary>
      /// Sets the date. (Uses invariant culture for parsing.)
      /// </summary>
      /// <param name="dateTime">The date time.</param>
      public void SetDate(string dateTime)
      {
         Date = DateTime.Parse(dateTime, CultureInfo.InvariantCulture).ToString("MM\\/dd\\/yyyy");
      }

      /// <summary>
      /// Equalses the specified other.
      /// </summary>
      /// <param name="other">The other.</param>
      /// <returns></returns>
      /// <exception cref="System.NotImplementedException"></exception>
      public bool Equals(YnabRecord other)
      {
         bool isEqual = true;

         isEqual &= (String.Compare(Date, other.Date, StringComparison.InvariantCulture) == 0);
         isEqual &= (String.Compare(Payee, other.Payee, StringComparison.InvariantCulture) == 0);
         isEqual &= (String.Compare(Category, other.Category, StringComparison.InvariantCulture) == 0);
         isEqual &= (String.Compare(Memo, other.Memo, StringComparison.InvariantCulture) == 0);
         isEqual &= (String.Compare(Inflow, other.Inflow, StringComparison.InvariantCulture) == 0);
         isEqual &= (String.Compare(Outflow, other.Outflow, StringComparison.InvariantCulture) == 0);

         return isEqual;
      }

      /// <summary>
      /// Returns a <see cref="System.String" /> that represents this instance.
      /// </summary>
      /// <returns>
      /// A <see cref="System.String" /> that represents this instance.
      /// </returns>
      public override string ToString()
      {
         var builder = new StringBuilder();

         builder.Append(GetType());
         builder.Append(" { ");
         builder.AppendFormat("Date='{0}', ", Date);
         builder.AppendFormat("Payee='{0}', ", Payee);
         builder.AppendFormat("Category='{0}', ", Category);
         builder.AppendFormat("Memo='{0}', ", Memo);
         builder.AppendFormat("Inflow='{0}', ", Inflow);
         builder.AppendFormat("Outflow='{0}' ", Outflow);
         builder.Append("}");

         return builder.ToString();
      }
   }
}
